<script setup>
import { Handle, Position, useVueFlow } from '@vue-flow/core'
import { java } from '@codemirror/lang-java'
import CodeMirror from 'vue-codemirror6'

import { computed, onMounted, ref, watch } from 'vue'
import { oneDark } from '@codemirror/theme-one-dark'
import { json } from '@codemirror/lang-json'
import { basicSetup } from 'codemirror'
import axios from 'axios'
import { nanoid } from 'nanoid'
import { usePluginStore } from 'stores/plugin-store.js'
import { storeToRefs } from 'pinia'
import { VueDraggable } from 'vue-draggable-plus'

const emits = defineEmits(['reSortHandles', 'updateNodeInternals'])

const props = defineProps([
  'id',
  'data',
  'position',
  'type',
  'events',
  'selected',
  'resizing',
  'dragging',
  'connectable',
  'dimensions',
  'isValidTargetPos',
  'isValidSourcePos',
  'parent',
  'parentNodeId',
  'zIndex',
  'targetPosition',
  'sourcePosition',
  'label',
  'dragHandle',
  'withInput',
  'withOutput',
  'withInputHandle',
])
const loading = ref(false)
const updateLoading = (loadingFlag) => {
  loading.value = loadingFlag
}
const dataConfig = props.data.config
const handles = computed({
  get: () => props.data.handles,
  set: (handles) => {
    updateNodeData(props.id, { handles })
    emits('reSortHandles', handles)
  },
})

const { updateNodeData } = useVueFlow()
const name = computed({
  get: () => props.data.name,
  set: (name) => {
    updateNodeData(props.id, { name })
  },
})
const extensions = [basicSetup, java(), oneDark]
const extensions_json = [basicSetup, json(), oneDark]
const nodeStatus = ref({
  remainNumb: 0,
  recNumb: 0,
  sendNumb: 0,
})
const store = usePluginStore()
const { handlerByPluginId } = storeToRefs(store)

function countChain() {
  axios.get('/transflow/node/status?nodeId=' + props.id).then((response) => {
    nodeStatus.value = response.data
  })
}

const { updateNodeInternals } = useVueFlow()
const saveNode = () => {
  loading.value = true
  axios
    .post('/transflow/node/save', props)
    .then(() => {
      updateNodeInternals([props.id])
      loading.value = false
      completeDirty()
    })
    .catch(() => {
      loading.value = false
    })
}
const handleSetting = ref({})
const showPropertiesPanel = ref(false)
onMounted(() => {
  handleSetting.value = handlerByPluginId.value(props.data.pluginId).handler
})
const enumIcon = ()=>{
  switch(props.data.nodeType){
    case 'INPUT':
      return 'input';
    case 'GATEWAY':
      return 'blur_linear'
    case 'OUTPUT':
      return 'output'
    default: return props.data.nodeType;
  }
}

const isDirty = ref(false)
watch(
  () => props.data,
  async () => {
    isDirty.value = true
  },
  { immediate: false, deep: true },
)
const completeDirty = ()=>{
  isDirty.value = false
}
defineExpose({ updateLoading, saveNode })
</script>

<template>
  <q-card class="text-white" style="min-width: 300px">
    <q-inner-loading :showing="loading">
      <q-spinner-gears size="50px" color="primary" />
    </q-inner-loading>
    <!-- 状态下拉面板 -->
    <q-expansion-item expand-icon-class="text-white" @show="countChain" expand-icon-toggle>
      <template v-slot:header>
        <q-item-section avatar>
          <q-avatar>
            <q-icon :name="enumIcon()"/>
          </q-avatar>
        </q-item-section>
        <q-item-section>
          <div class="text-h6">{{ name }}</div>
          <q-badge color="red" rounded floating v-if="isDirty"/>
          <div class="text-subtitle2">{{ data.pluginId }}</div>
          <q-popup-edit v-model="name" auto-save v-slot="scope">
            <q-input v-model="scope.value" dense autofocus counter />
          </q-popup-edit>
        </q-item-section>
      </template>
      <q-card dark class="bg-positive text-white">
        <q-list dense padding class="full-width">
          <q-item class="text-subtitle2" clickable>接收：{{ nodeStatus.recNumb }}</q-item>
          <q-item class="text-subtitle2" clickable>发送：{{ nodeStatus.sendNumb }}</q-item>
        </q-list>
      </q-card>
    </q-expansion-item>
    <q-separator dark />
    <!-- 配置参数面板 -->
    <q-card-section class="nodrag q-px-none q-py-xs" v-if="data.properties?.length > 0">
      <q-btn
        class="full-width"
        flat
        square
        label="参数配置"
        align="left"
        @click="showPropertiesPanel = true"
      />
      <!-- 参数配置弹窗 -->
      <q-dialog
        v-model="showPropertiesPanel"
        persistent
        transition-show="flip-down"
        transition-hide="flip-up"
      >
        <q-card dark class="text-white" style="min-width: 400px">
          <q-bar>
            <div>参数配置</div>
            <q-space />
            <q-btn dense flat icon="close" v-close-popup>
              <q-tooltip class="bg-white text-primary">Close</q-tooltip>
            </q-btn>
          </q-bar>

          <q-card-section>
            <div v-for="property in data.properties" :key="property.key">
              <div class="column">
                <div class="col text-overline">
                  {{ property.label }}
                </div>
                <div class="col">
                  <code-mirror
                    v-if="property.type === 'json'"
                    v-model="dataConfig[property.key]"
                    :wrap="true"
                    :tabSize="4"
                    :extensions="[extensions_json]"
                  />
                  <code-mirror
                    v-else-if="property.type === 'code'"
                    v-model="dataConfig[property.key]"
                    :wrap="true"
                    :tabSize="4"
                    :extensions="[extensions]"
                  />
                  <q-input
                    v-else
                    dark
                    :type="property.type === 'password' ? 'password' : 'text'"
                    bg-color="blue-grey-10"
                    v-model="dataConfig[property.key]"
                    dense
                    borderless
                    square
                    standout
                  />
                </div>
              </div>
            </div>
          </q-card-section>
          <q-card-actions align="right">
            <q-btn flat @click="saveNode" v-close-popup>保存</q-btn>
          </q-card-actions>
        </q-card>
      </q-dialog>
    </q-card-section>
    <!-- 处理器面板 -->
    <q-card-section class="nodrag q-px-none q-py-xs">
      <!-- 首行提示subject -->
      <div class="row">
        <div class="text-overline q-ml-md">{{ handleSetting?.label || '处理器' }}</div>
        <q-btn
          dense
          flat
          label="+"
          size="small"
          @click="
            handles.push({
              id: nanoid(),
              value: '',
            })
          "
        ></q-btn>
      </div>
      <!-- 可拖拽处理器 -->
      <VueDraggable
        group="internal-group"
        v-model="handles"
        @dragover.prevent.stop
        handle=".sort-handle"
        :animation="150"
      >
        <q-item
          dense
          v-for="(handler, index) in handles"
          :key="handler.id + index"
          class="q-px-none"
        >
          <q-item-section class="no-padding">
            <q-btn class="full-width btn-fixed-width" flat square>
              <Handle
                :id="handler.id"
                type="target"
                :position="Position.Left"
                v-if="withInput && withInputHandle"
              />
              <i
                class="q-icon on-left notranslate material-icons sort-handle cursor-move"
                aria-hidden="true"
                role="img"
                >reorder</i
              >
              <span class="block">{{ handler.name || '处理器' + index }}</span>
              <q-space />
              <Handle :id="handler.id" type="source" :position="Position.Right" v-if="withOutput" />
              <q-popup-proxy transition-show="flip-up" transition-hide="flip-down">
                <q-card dark style="min-width: 200px">
                  <q-bar>
                    <q-input dark v-model="handler.name"></q-input>
                    <q-space />
                    <q-btn
                      dense
                      flat
                      icon="delete"
                      color="red"
                      @click="
                        () => {
                          $q.dialog({
                            title: '删除？',
                            message: '确定删除这条处理器？',
                          }).onOk((data) => {
                            handles.splice(index, 1)
                          })
                        }
                      "
                    />
                  </q-bar>
                  <code-mirror
                    v-model="handler.value"
                    :wrap="true"
                    :tabSize="4"
                    :extensions="[extensions]"
                  />
                </q-card>
              </q-popup-proxy>
            </q-btn>
          </q-item-section>
        </q-item>
      </VueDraggable>
    </q-card-section>
  </q-card>
  <Handle type="target" :position="Position.Left" v-if="withInput && !withInputHandle" />
  <Handle type="source" v-if="withOutput && handles.length === 0" :position="Position.Right" />
</template>
<style scoped></style>
